#ifndef __COMMON_NETWORK__
#define __COMMON_NETWORK__

#include <winsock2.h>
#include <string>
#include <cassert>
#include <list>
#include <algorithm>
#include "CommonThread.h"
#include "CommonNetwork.h"


using namespace std;

enum NETWORK_CODE
{
	NC_NONE,
	NC_TCP_LISTENING,
	NC_TCP_ACCEPT,
	NC_TCP_CLIENT,
	NC_UDP
};


typedef in_addr ip;		// network byte order.
typedef u_short port;   // network byte order.

typedef pair<int, u_short>	target_info;

class network
{
private:
	typedef std::list<target_info> target_group;	// for UDP multicast emulation.

private:
	SOCKET		m_sock;
	SOCKADDR_IN	m_addr;
	int			m_addrlen;

	long		m_ResultEventProcess;
	WSAEVENT	m_Event;

	CRITICAL_SECTION	m_SendCriticalSection;	
	CRITICAL_SECTION	m_RecvCriticalSection;
	NETWORK_CODE		m_NetworkType;		

	target_group		m_MulticastGroup;	// only used udp sending

	bool InitializeListening(string ip, int port);
	bool InitializeAccept(const network* listening);
	bool InitializeClient( string ip, int port);
	bool InitializeUDP( string ip, int port);	

public:
	network(void);
	~network();

	bool Initialize(NETWORK_CODE networkcode, string ip, int port);
	bool Initialize(const network* listening);

	bool Attribute(int level, int optname, const char* optval,int optlen); // setting socket option method. 
		
	bool SetEvent(long Events);
	void EventProcess(unsigned int msTimeout = 0);
	bool CheckEvent(long EventCode);	
	
	bool Send(const char* buf, int len);
	bool SendUDP(const char* buf, int len, ip recvIP, port port);
	bool SendGroup(const char* buf, int len);	// only UDP;

	bool Recv(char* buf, const int len, int* reallen);
	bool RecvUDP(char* buf, const int len, int* reallen, ip* recvIP, port* port);

	SOCKET			GetSocket(void) const;
	in_addr			GetLinkIP(void);
	NETWORK_CODE	GetNetworkType(void);

	void	AddMulticastGroup(ip TargetIP, port TargetPort);
	bool	DeleteMulticastGroup(ip TargetIP, port TargetPort);

	bool Close(void);
};

#endif